package com.ruicar.afs.cloud.account.common.send;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.account.common.entity.VoucherFlowInfo;
import com.ruicar.afs.cloud.account.common.processor.constant.VoucherConstant;
import com.ruicar.afs.cloud.account.common.processor.impl.VoucherItemRequest;
import com.ruicar.afs.cloud.account.common.processor.impl.msg.VoucherItemSendProcessor;
import com.ruicar.afs.cloud.account.common.service.VoucherFlowInfoService;
import com.ruicar.afs.cloud.common.modules.contract.enums.VoucherSendStatus;
import com.ruicar.afs.cloud.common.modules.constant.VoucherBuriedPointNo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 财务凭证发送service
 */

@Slf4j
@Service
@AllArgsConstructor
@Component
public class VoucherItemSendService {
    private final VoucherItemSendProcessor voucherItemSendProcessor;
    private final StringRedisTemplate stringRedisTemplate;
    private final VoucherFlowInfoService voucherFlowInfoService;
    private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(50, 60,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024));

    public void voucherItemSend(){
        String id = null;
        Boolean isFinish = false;
        List<VoucherFlowInfo> dtos = new ArrayList<>();
        while (!isFinish) {
            try {
                while (true) {
                    //合同激活时，需要发送凭证辅助帐
                   IPage iPage = voucherFlowInfoService.page(new Page<>(1, VoucherConstant.querySize),
                            Wrappers.<VoucherFlowInfo>lambdaQuery().eq(VoucherFlowInfo::getItemStatus, VoucherSendStatus.NOT_SEND).eq(VoucherFlowInfo::getBuriedPointNo, VoucherBuriedPointNo.contractActivation)
                                    .gt(StringUtil.isNotBlank(id), VoucherFlowInfo::getId, id).orderByAsc(VoucherFlowInfo::getId));

                   List<VoucherFlowInfo>  voucherFlowInfos=iPage.getRecords();
                    if (CollectionUtil.isEmpty(voucherFlowInfos)) {
                        isFinish = true;
                        break;
                    }
                    dtos.addAll(voucherFlowInfos);
                    id = String.valueOf(voucherFlowInfos.get(voucherFlowInfos.size() - 1).getId());
                    stringRedisTemplate.opsForValue().set(VoucherConstant.templateKey(VoucherConstant.VOUCHER_SYNC_KEY), String.valueOf(id));
                    if (dtos.size() >= 100000) break;
                }
                if (dtos.size() != 0) {
                    this.execute(dtos);
                    dtos.clear();
                }
            } catch (Exception e) {
                isFinish = true;
                log.error("凭证发送任务执行失败------", e);
            } finally {
                isFinish = true;
            }
        }
    }
    public void execute(List<VoucherFlowInfo> list) {
        try {
            for (VoucherFlowInfo voucherFlowInfo : list) {
                VoucherItemRequest request =new VoucherItemRequest();
                request.setVoucherFlowInfo(voucherFlowInfo);
                EXECUTOR_SERVICE.submit(new VoucherItemSendRunner(request, voucherItemSendProcessor));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }

    }
    @AllArgsConstructor
    private static class VoucherItemSendRunner implements Runnable {
        private VoucherItemRequest request;
        private VoucherItemSendProcessor voucherItemSendProcessor;
        @Override
        public void run() {
            try {
                voucherItemSendProcessor.process(request);
            } catch (Exception e) {
                log.error("", e);
            } finally {
            }
        }
    }


}
